package ru.simplemaps.osmapi;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import ru.simplemaps.osmapi.objects.*;

/**
 * SAX content handler for parsing OSM data
 *
 * @author enaku_adm
 * @since 22.07.2010 11:30:57
 */
public class OSMContentHandler implements ContentHandler {
    public static final String TAG = "tag";

    public static final String NODE = "node";
    public static final String WAY = "way";
    public static final String RELATION = "relation";

    public static final String MEMBER = "member";
    public static final String ND = "nd";
    public static final String ROLE = "role";
    public static final String TYPE = "type";

    public static final String K = "k";
    public static final String V = "v";

    public static final String ID = "id";
    public static final String REF = "ref";

    public static final String LAT = "lat";
    public static final String LON = "lon";

    private Locator locator;
    private OSMData data;

    /**
     * Current processing element
     */
    private AbstractOSMElement currentElement;

    public OSMData getData() {
        return data;
    }

    public void setDocumentLocator(Locator locator) {
        this.locator = locator;
    }

    public void startDocument() throws SAXException {
        data = new OSMData();
    }

    public void endDocument() throws SAXException {
    }

    public void startPrefixMapping(String prefix, String uri) throws SAXException {
    }

    public void endPrefixMapping(String prefix) throws SAXException {
    }

    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
        if (NODE.equals(qName)) {
            Node node = new Node(
                    Long.valueOf(atts.getValue(ID)),
                    Double.valueOf(atts.getValue(LAT)),
                    Double.valueOf(atts.getValue(LON))
            );

            data.nodes.put(node.id, node);
            currentElement = node;
        } else if (WAY.equals(qName)) {
            Way way = new Way(
                    Long.valueOf(atts.getValue(ID))
            );
            data.ways.put(way.id, way);
            currentElement = way;
        } else if (RELATION.equals(qName)) {
            Relation relation = new Relation(
                    Long.valueOf(atts.getValue(ID))
            );
            data.relations.put(relation.id, relation);
            currentElement = relation;
        } else if (TAG.equals(qName)) {
            if (currentElement != null) {
                currentElement.setTag(atts.getValue(K), atts.getValue(V));
            }
        } else if (ND.equals(qName)) {
            if (currentElement != null && currentElement instanceof Way) {
                Way currentWay = (Way) currentElement;
                currentWay.addNode(Long.valueOf(atts.getValue(REF)));
            }
        } else if (MEMBER.equals(qName)) {
            if (currentElement != null && currentElement instanceof Relation) {
                Relation currentRelation = (Relation) currentElement;
                currentRelation.members.add(
                        new Relation.Member(
                                OSMElementType.valueOf(atts.getValue(TYPE)),
                                Long.valueOf(atts.getValue(REF)),
                                atts.getValue(ROLE)
                        )
                );
            }
        }
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
    }

    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
    }

    public void processingInstruction(String target, String data) throws SAXException {
    }

    public void skippedEntity(String name) throws SAXException {
    }
}
